package srzy.socket

import scala.actors.Actor
import scala.actors.Actor._
import srzy.common._
import srzy.rb._
import scala.actors.TIMEOUT
import java.net.SocketTimeoutException

class ReceActor(msgActor: MsgActor) extends Actor with srzy.common.Logging {

  override def act = {
    loop {
      //      reactWithin(1000) {
      receiveWithin(1000) {
        case 'exit => {
          sender ! 'ok
          exit()
        }
        case TIMEOUT =>
          {
            try {
              val msg = msgActor.socketConn.read
              srzy.rb.getMsgType(msg) match {
                case srzy.rb.CODE_KAR => {
                  logger.debug("heartbeat rece")
                  val heartMsg = SocketConn.heartMsg.replaceAll(":TIME",
                    srzy.common.Common.getSysTime("yyyyMMddhhmmssSS"))
                  msgActor.socketConn.write(heartMsg)
                }
                case srzy.rb.CODE_ECA => {
                  logger.debug("authentication rece")
                }
                case i: Int => {
                  logger.debug("service msg rece [" + i + "]")
                  msgActor ! ('rece, msg)
                }
              }
            } catch {
              case ste: SocketTimeoutException =>
            }

          }
      }
    }
  }

  override def exceptionHandler = {
    case ioe: java.io.IOException => {
      logger.error(ioe.getMessage(), ioe)
      sys.exit
    }
    case e: Exception => logger.error(e.getMessage(), e)
  }

}

class MsgActor extends Actor with srzy.common.Logging {

  val socketConn = SocketConn()

  var oc: scala.actors.OutputChannel[Any] = null

  var receActor: ReceActor = null

  override def act = {
    loop {
      react {
        case sendMsg: String => {
          if (oc == null) {
            socketConn.write(sendMsg)
            oc = sender
          } else {
            logger.error("The message has not been returned, please waiting for the return")
          }
        }
        case ('rece, receMsg: String) => {
          oc ! receMsg
          oc = null
        }
        case 'exit => {
          (receActor !! 'exit).apply
          socketConn.close
          sender ! 'ok
          exit()
        }
        case a: Any => logger.error("unknown pattern " + a.toString)
      }
    }
  }

  override def start(): Actor = synchronized {
    super.start()
    receActor = new ReceActor(this)
    receActor.start
    this
  }

  override def exceptionHandler = {
    case ioe: java.io.IOException => {
      logger.error(ioe.getMessage(), ioe)
      sys.exit
    }
    case e: Exception => logger.error(e.getMessage(), e)
  }

}

object MsgActor extends Actor with srzy.common.Logging {

  val socketNum = Integer.parseInt(Config.getOptionValue("root", "config", "SocketNum").getOrElse("1"))
  var i = 0
  val actorList = List.fill(socketNum)(new MsgActor)
  actorList.map(_.start)

  override def act = {
    loop {
      react {
        case sendMsg: String => {
          val sub = i % socketNum
          val receMsg = (actorList.apply(sub) !! sendMsg).apply
          sender ! receMsg
          i += 1
        }
        case 'exit => {
          actorList.map(x => (x !! 'exit).apply)
          sender ! 'ok
          exit()
        }
        case a: Any => logger.error("unknown pattern " + a.toString)
      }
    }

  }

}